package com.feinno.urcs.group.service;

import com.feinno.cpim.CpimHeader;
import com.feinno.cpim.CpimMessage;
import com.feinno.urcs.feature.Capability;
import com.feinno.urcs.group.GroupConfiguration;
import com.feinno.urcs.group.api.AndPcStatusService;
import com.feinno.urcs.group.api.GroupCacheManager;
import com.feinno.urcs.group.api.GroupTerminalService;
import com.feinno.urcs.group.entity.GroupMember;
import com.feinno.urcs.group.entity.GroupMessageType;
import com.feinno.urcs.group.pctask.task.AndPcGroupMsgArgs;
import com.feinno.urcs.group.pd.task.entity.PdRemoveGroupMemberNotifyArgs;
import com.feinno.urcs.group.siptask.task.GroupByeArgs;
import com.feinno.urcs.group.siptask.task.GroupInviteArgs;
import com.feinno.urcs.group.siptask.task.GroupMessageArgs;
import com.feinno.urcs.group.siptask.task.GroupTaskEvents;
import com.feinno.urcs.group.util.CpimUtils;
import com.feinno.urcs.group.util.DateUtils;
import com.feinno.urcs.group.util.MSRPTextMsgParser;
import com.feinno.urcs.group.util.MsrpContent;
import com.feinno.urcs.mobile.UserLocatorService;
import com.feinno.urcs.mobile.entity.UserType;
import com.feinno.urcs.profile.UserSessionService;
import com.feinno.urcs.profile.entity.ClientType;
import com.feinno.urcs.profile.entity.PcCapacity;
import com.feinno.urcs.profile.entity.UeAccess;
import com.feinno.urcs.sip.UrcsSipFactory;
import com.feinno.urcs.types.MobileNo;
import com.feinno.util.StringUtils;
import freemarker.template.utility.StringUtil;
import org.helium.framework.annotations.ServiceImplementation;
import org.helium.framework.annotations.ServiceSetter;
import org.helium.framework.annotations.TaskEvent;
import org.helium.framework.task.TaskProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sip.address.SipURI;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by honghao on 6/29/15.
 */
@ServiceImplementation
public class GroupTerminalServiceImpl implements GroupTerminalService {
	private static final Logger LOGGER = LoggerFactory.getLogger(GroupTerminalServiceImpl.class);

	@ServiceSetter
	private UserSessionService userSessionService;
	@ServiceSetter
	private GroupCacheManager groupCache;
	@TaskEvent(GroupTaskEvents.GROUP_INVITE)
	private TaskProducer<GroupInviteArgs> adInviteTask;
	@TaskEvent(GroupTaskEvents.GROUP_PD_INVITE)
	private TaskProducer<GroupInviteArgs> pdInviteTask;
	@TaskEvent(GroupTaskEvents.GROUP_SESSION_MODE_MESSAGE)
	private TaskProducer<GroupMessageArgs> adMessageTask;
	@TaskEvent(GroupTaskEvents.GROUP_PD_MESSAGE)
	private TaskProducer<GroupMessageArgs> pdMessageTask;
	@TaskEvent(GroupTaskEvents.GROUP_PD_MEMBER_NOTIFY)
	private TaskProducer<PdRemoveGroupMemberNotifyArgs> pdGroupMemberNotifyTask;
	@TaskEvent(GroupTaskEvents.GROUP_BYE)
	private TaskProducer<GroupByeArgs> byeTask;
	@TaskEvent(GroupTaskEvents.GROUP_MESSAGE_TO_PC)
	private TaskProducer<AndPcGroupMsgArgs> andPcGroupMsgTask;
	@ServiceSetter
	private UserLocatorService userLocatorService;
	@ServiceSetter
	private AndPcStatusService andPcStatusService;

	@Override
	public void inviteJoinGroup(GroupInviteArgs args) {
		try {
			adInviteTask.produce(args);
		} catch (RuntimeException e) {
			LOGGER.warn(String.format(" inviteJoinGroup error,args=%s", args));
		}
	}

	@Override
	public void sendTextMessage(GroupMessageArgs args) {
		boolean isSendUE = !(userSessionService.hasPcCapacity(args.getToMobile(), PcCapacity.IM_CC));
		try {
			// 仅仅为了激活用户, 下发离线消息.
			if (args.isOnlyActiveOfflineMsg()) {
				// 到这里的是一个不完整的参数, 如果用来干其他业务会因为缺少参数出异常.
				adMessageTask.produce(args);
				LOGGER.info(String.format("acitve GroupOfflineMessage args=%s", args.toJsonObject().toString()));
				return;
			}

			if (args.getFromMobile().equals(args.getToMobile())) {
				if (args.isFromFetion()) {
					AndPcGroupMsgArgs andPcGroupMsgArgs = getAndPcGroupMsgArgs(args);
					andPcGroupMsgTask.produce(andPcGroupMsgArgs);
					if (isSendUE)
						sendTextMsgToUE(args);
				} else {
					if (args.getIsPc()) {
						if (isSendUE)
							sendTextMsgToUE(args);
					} else {
						AndPcGroupMsgArgs andPcGroupMsgArgs = getAndPcGroupMsgArgs(args);
						andPcGroupMsgTask.produce(andPcGroupMsgArgs);
					}
				}
			} else {
				AndPcGroupMsgArgs andPcGroupMsgArgs = getAndPcGroupMsgArgs(args);
				andPcGroupMsgTask.produce(andPcGroupMsgArgs);
				if (isSendUE)
					sendTextMsgToUE(args);
			}
		} catch (Exception e) {
			LOGGER.warn(String.format(" sendTextMessage error,args=%s, error :{}", args), e);
		}
	}

	private void sendTextMsgToUE(GroupMessageArgs args) throws Exception {
		MsrpContent content = new MsrpContent(args.getContent());
		LOGGER.info("GroupSessionMessageTask.processTask, send text....");
		String message = MSRPTextMsgParser.getMsrpMsgContent(content);
		Matcher m = Pattern.compile("<Font.*?>([\\s\\S]*?)</Font>").matcher(message);
		boolean hasFont = false;
		while (m.find()) {
			message = m.group(1).trim();
			hasFont = true;
		}
		byte[] buffer;
		if (hasFont) {
			buffer = message.getBytes();
		} else {
			String s = content.getContentTransferEncoding().trim().toLowerCase();
			if ("base64".equalsIgnoreCase(s)) {
				buffer = Base64.getDecoder().decode(content.getContent());
			} else {
				buffer = content.getContent().getBytes();
			}
		}
		SipURI groupUri = UrcsSipFactory.getAddressFactory().createSipURI(GroupConfiguration.INSTANCE.getGroupPrefix() + args.getGroupId(), GroupConfiguration.INSTANCE.getGroupDomain());
		CpimMessage cpim = CpimUtils.createCpim(buffer, args.getFromMobile(), groupUri, content.getContentType(), true, args.getSendTime());
		// 群@
		if (args.getAtMembers() != null) {
			if (args.getAtMembers().size() > 0) {
				StringBuilder sb = new StringBuilder();
				for (MobileNo mobileNo : args.getAtMembers()) {
					sb.append(String.format("tel:%s", mobileNo));
					sb.append(";");
				}
				String ccValue = sb.toString().substring(0, sb.length() - 1);
				CpimHeader ccHeader = new CpimHeader("cc", ccValue);
				cpim.addHeader(ccHeader);
			}
		}
		if (!StringUtils.isNullOrEmpty(content.getCc())) {
			CpimHeader ccHeader = new CpimHeader("cc", content.getCc());
			cpim.addHeader(ccHeader);
		}
		args.setContent(cpim.getByteArray());

		adMessageTask.produce(args);
	}

	private AndPcGroupMsgArgs getAndPcGroupMsgArgs(GroupMessageArgs args) throws IllegalAccessException, InstantiationException, IOException, ParseException {
		GroupMember groupMemberInfo = groupCache.getGroupMemberInfo(args.getGroupId(), args.getFromMobile());
		String senderName = groupMemberInfo.getDisplayname();
		AndPcGroupMsgArgs andPcGroupMsgArgs = new AndPcGroupMsgArgs();
		MsrpContent content = new MsrpContent(args.getContent());
		andPcGroupMsgArgs.setContent(MSRPTextMsgParser.getMsrpMsgContent(content).getBytes("UTF-8"));
		andPcGroupMsgArgs.setGroupId(args.getGroupId());
		andPcGroupMsgArgs.setDomain(args.getDomain());
		andPcGroupMsgArgs.setConversationId(args.getConversationId());
		andPcGroupMsgArgs.setSubject(args.getSubject());
		andPcGroupMsgArgs.setSender(args.getFromMobile());
		andPcGroupMsgArgs.setToMobile(args.getToMobile());
		andPcGroupMsgArgs.setSendTime(args.getSendTime());
		String contentType = content.getContentType().trim();
		if (contentType.equals("text/plain")) {
			andPcGroupMsgArgs.setContentType(GroupMessageType.TEXT);
		} else if (contentType.equals("application/cloudfile+xml")) {
			andPcGroupMsgArgs.setContentType(GroupMessageType.CLOUDFILE);
		} else if (contentType.equals("application/vemoticon+xml")) {
			andPcGroupMsgArgs.setContentType(GroupMessageType.OUTCE);
		} else if (contentType.equals("application/vnd.gsma.rcspushlocation+xml")) {
			andPcGroupMsgArgs.setContentType(GroupMessageType.LOCATION);
		}
		andPcGroupMsgArgs.setSenderName(StringUtils.isNullOrEmpty(senderName) ? groupMemberInfo.getMobileNo().getMobile() : senderName);
		MsrpContent msrp = new MsrpContent(args.getContent());
		if (!StringUtils.isNullOrEmpty(msrp.getCc())) {
			String value = msrp.getCc();
			String[] ats = value.split(";");
			List<MobileNo> list = new ArrayList<>();
			for (String at : ats) {
				MobileNo atMobile = MobileNo.parseFrom(at);
				list.add(atMobile);
			}
			andPcGroupMsgArgs.setGroupAtMembers(list);
		}
		if (args.getAtMembers() != null && args.getAtMembers().size() > 0) {
			andPcGroupMsgArgs.setGroupAtMembers(args.getAtMembers());
		}
		return andPcGroupMsgArgs;
	}


	@Override
	public void kickMember(GroupByeArgs args) {
		byeTask.produce(args);
	}

	@Override
	public void silenced(GroupByeArgs args) {
		byeTask.produce(args);
	}


}
